######################################################################
package Swignition::RDFModel::Smusher;
######################################################################

use Swignition::RDFModel::Subject;
use Swignition::RDFModel::Property;
use Swignition::RDFModel::Value;

sub smush
{
	my $graph = shift;
	my @input = ($graph, @_);
	
	my @EPs = ();
	foreach my $g (@input)
		{ push @EPs, [ find_equality_properties($g) ]; }
		
	# actually do smushing here.

	my @FPs = ();
	foreach my $g (@input)
		{ push @FPs, [ find_functional_properties($g) ]; }

	my @IFPs = ();
	foreach my $g (@input)
		{ push @IFPs, [ find_inverse_functional_properties($g) ]; }

	# actually do smushing here.
}


sub find_functional_properties
{
	
}

sub find_inverse_functional_properties
{
}


sub find_equality_properties
# This function (and its underscore-prefixed partner) finds out which properties
# are the same as owl:sameAs. Usually, people will just use owl:sameAs directly,
# but if they want to say "ex:isSame owl:sameAs owl:sameAs" then we will let
# them.
# Really we should also find subproperties of owl:sameAs too!
{
	my $graph  = shift;
	my @props  = ('http://www.w3.org/2002/07/owl#sameAs');
	my $doneSomething = 1;
	
	while ($doneSomething)
	{
		my @newProps = _find_equality_properties($graph, @props);
		
		if ((scalar @props) eq (scalar @newProps))
		{
			$doneSomething = 0;
		}
		else
		{
			@props = @newProps;
		}
	}
	
	return @props;
}

# Really, need to keep running this until the list stabilises.
sub _find_equality_properties
{
	my $graph  = shift;
	my @known  = @_;
	my $sameAs = {};
	my $rv     = {};
	
	foreach my $k (@known)
	{
		foreach my $subject (keys %$graph)
		{
			my $s = $graph->{$subject};
			
			# Should look not just for owl:sameAs, but *all* known equality props.
			if (defined $s->{'properties'}->{$k})
			{
				my $p = $s->{'properties'}->{$k};
			
				foreach my $value (@{ $p->{'values'} })
				{
					next unless ($value->type);
					push @{ $sameAs->{ $value->toString } }, $subject;
					push @{ $sameAs->{ $subject } }, $value->toString;
				}
			}
		}
				
		$rv->{$k} = 1;
	}
	
	my $doneSomething = 1;
	while ($doneSomething > 0)
	{
		$doneSomething = 0;
		foreach my $prop (keys %$rv)
		{
			if (defined $sameAs->{ $prop })
			{
				foreach my $sameThing ( @{ $sameAs->{ $prop } } )
				{
					next if defined($rv->{$sameThing});
					$doneSomething++;
					
					$rv->{$sameThing}++;
				}
			}
		}
	}
	
	return (sort keys %$rv);
}

1;
